package jesss.commands;

import com.amazonaws.AmazonClientException;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.ObjectMetadata;
import jesss.options.ExtendedGnuParser;
import jesss.options.JesssOptions;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.MissingArgumentException;
import org.apache.commons.cli.Options;

import java.io.File;

/**
 * User: Lee
 * Date: 8/24/13
 * Time: 1:30 PM
 */
public class GetObjectCommand<T> extends AbstractJesssCommand {

    private JesssOptions jesssOptions = null;
    private Options options = new Options();
    private String bucketName;
    private String key;
    private String targetFilePath;

    public GetObjectCommand(JesssOptions jesssOptions) throws Exception {
        this.jesssOptions = jesssOptions;
        setOptions();
        try {
            parseArgs(jesssOptions.getArgs());
        } catch (Exception e) {
            printUsage();
            throw e;
        }
    }

    @Override
    public CommandResult<ObjectMetadata> executeCommand() {
        CommandResult<ObjectMetadata> commandResult = new CommandResult<>();

        try {
            GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, key);
            ObjectMetadata objectMetadata = jesssOptions.getAmazonS3().getObject(getObjectRequest, new File(targetFilePath));

            if (objectMetadata != null) {
                commandResult.setResultStatus(ResultStatus.Success);
                commandResult.setResultValue(objectMetadata);
                System.out.printf("ObjectMetadata {ETag=%s, Length=%s, CacheControl=%s, ContentEncoding=%s, ExpirationTime=%s, VersionID=%s, MD5=%s}%n",
                        objectMetadata.getETag(),
                        objectMetadata.getContentLength(),
                        objectMetadata.getCacheControl(),
                        objectMetadata.getContentEncoding(),
                        objectMetadata.getExpirationTime(),
                        objectMetadata.getVersionId(),
                        objectMetadata.getContentMD5());
            }
        } catch (AmazonClientException e) {
            commandResult.setResultStatus(ResultStatus.Error);
            commandResult.setStatusMessage(String.format("Unable to get object with bucket \"%s\" and key \"%s\".",bucketName, key));
            addExceptionInfoToCommandResult(commandResult, e);
        }

        return commandResult;
    }

    private void setOptions() {
        options = new Options();
        options.addOption("bn", "bucketName", true, "Bucket name to list objects from");
        options.addOption("k", "key", true, "Key");
        options.addOption("tf", "targetFile", true, "Target file");
    }

    private void parseArgs(String[] args) throws Exception {
        if (args == null || args.length == 0) {
            printUsage();
        }

        try {
            CommandLineParser parser = new ExtendedGnuParser(true);
            CommandLine cmd = parser.parse(options, args);

            if (cmd.hasOption("bn")) {
                bucketName = cmd.getOptionValue("bn");
            } else {
                throw new MissingArgumentException("Missing bucket name parameter.");
            }

            if (cmd.hasOption("k")) {
                key = cmd.getOptionValue("k");
            } else {
                throw new MissingArgumentException("Missing key parameter.");
            }

            if (cmd.hasOption("tf")) {
                targetFilePath = cmd.getOptionValue("tf");
                if (new File(targetFilePath).exists()) {
                    throw new IllegalArgumentException(String.format("The target file \"%s\" already exists.", targetFilePath));
                }
            } else {
                throw new MissingArgumentException("Missing source file path parameter.");
            }
        } catch (Exception e) {
            printUsage();
            throw e;
        }
    }

    private void printUsage() {
        System.out.println("Usage:");
        System.out.println("jesss.jesss -cn getObject -bn <mybucket> -k <key> -tf <local file name>");
    }
}
